// File: CsoGateway.System.TimeSpan.js
// Version: 0.7.1.0
// Author: Pascal Dufresne
// Date: 2009-10-08
// Last update: 2009-10-08
// http://csogateway.codeplex.com
// http://csogateway.metaobjects.ca
// Copyright (C) 2010 Pascal Dufresne

/*
 * Register CsoGateway.System namespace. Import CsoGateway.System namespace.
 */
Type.registerNamespace("CsoGateway.System");
ImportNamespace(CsoGateway.System);


/*
 * CsoGateway.System.TimeSpan represents a time interval. It's interface is meant to resemble
 * that of the .NET class System.TimeSpan.
 * The main difference is that CsoGateway.System.TimeSpan is precise to the millisecond while System.TimeSpan is precise to
 * 1/10000 of a millisecond (or 100 nanosecond).
 *
 *
 * Contructor                       'System.TimeSpan' equivalent
 * ----------                       -----------------------------------------------------------
 * TimeSpan(N, N, N)                TimeSpan(System.Int32, System.Int32, System.Int32)
 * TimeSpan(N, N, N, N)             TimeSpan(System.Int32, System.Int32, System.Int32, System.Int32)
 * TimeSpan(N, N, N, N, N)          TimeSpan(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32)
 *    .. where N is Number
 *
 * Fields                           'System.TimeSpan' equivalent
 * ----------                       -----------------------------------------------------------
 * MinValue                         MinValue
 * MaxValue                         MaxValue
 * Zero                             Zero
 *
 * Methods                          'System.TimeSpan' equivalent
 * ----------                       -----------------------------------------------------------
 * Days()                           Days
 * Hours()                          Hours
 * Milliseconds()                   Milliseconds
 * Minutes()                        Minutes
 * Seconds()                        Seconds
 * TotalDays()                      TotalDays
 * TotalHours()                     TotalHours
 * TotalMilliseconds()              TotalMilliseconds
 * TotalMinutes()                   TotalMinutes
 * TotalSeconds()                   TotalSeconds
 * 
 * Add(TimeSpan)                    Add(System.TimeSpan)
 * Compare(TimeSpan,TimeSpan)       Compare(System.TimeSpan, System.TimeSpan)
 * CompareTo(TimeSpan)              CompareTo(System.TimeSpan)
 * Duration()                       Duration()
 * Equals(TimeSpan)                 Equals(System.TimeSpan)
 * FromDays(Number)                 FromDays(System.Double)
 * FromHours(Number)                FromHours(System.Double)
 * FromMilliseconds(Number)         FromMilliseconds(System.Double)
 * FromMinutes(Number)              FromMinutes(System.Double)
 * FromSeconds(Number)              FromSeconds(System.Double)
 * Negate()                         Negate()
 * Parse(String)					Parse(System.String)
 * Substract(TimeSpan)              Substract(System.TimeSpan)
 * toString()                       ToString()
 * ToString()                       ToString()
 */
 
 
 /*
 * Creates a new CsoGateway.System.Timespan.
 * There are 4 ways to create a Dictionary object corresponding to 4 different constructors:
 * - TimeSpan(milliseconds)
 * - TimeSpan(hours, minutes, seconds)
 * - TimeSpan(days, hours, minutes, seconds)
 * - TimeSpan(days, hours, minutes, seconds, milliseconds)
 * 
 * All parameters must be integers between -9007199254740992 and 9007199254740992 inclusively or an exception is thrown. If the TimeSpan equivalent to
 * the specified parameters is not between -9007199254740992 and 9007199254740992 ms inclusively, an exception is thrown.
 * (9007199254740992 ms = 104249991 days, 8 hours, 59 minutes, 0 seconds, 992 milliseconds)
 *
 * Ref: System.TimeSpan.TimeSpan(Int64),
 *      System.TimeSpan.TimeSpan(Int32, Int32, Int32)
 *      System.TimeSpan.TimeSpan(Int32, Int32, Int32, Int32)
 *      System.TimeSpan.TimeSpan(Int32, Int32, Int32, Int32, Int32)
 */
CsoGateway.System.TimeSpan = function TimeSpan()
{	
	if((arguments.length == 0) || (arguments.length == 2) || (arguments.length >= 6))
	{
		throw new Error.parameterCount('CsoGateway.System.TimeSpan: Wrong number of arguments.');
	}
	
	if(arguments.length == 1)
	{
		AssertArgumentIsPreciseInteger(arguments[0]);
		
		this.milliseconds = arguments[0];
	}
	else if(arguments.length == 3)
	{
		AssertArgumentIsPreciseInteger(arguments[0]);
		AssertArgumentIsPreciseInteger(arguments[1]);
		AssertArgumentIsPreciseInteger(arguments[2]);
		
		this.milliseconds = ((60*60*1000*arguments[0]) + (60*1000*arguments[1]) + (1000*arguments[2]));
	}
	else if(arguments.length == 4)
	{
		AssertArgumentIsPreciseInteger(arguments[0]);
		AssertArgumentIsPreciseInteger(arguments[1]);
		AssertArgumentIsPreciseInteger(arguments[2]);
		AssertArgumentIsPreciseInteger(arguments[3]);
		
		this.milliseconds = ((24*60*60*1000*arguments[0]) + (60*60*1000*arguments[1]) + (60*1000*arguments[2]) + (1000*arguments[3]));
	}
	else if(arguments.length == 5)
	{
		AssertArgumentIsPreciseInteger(arguments[0]);
		AssertArgumentIsPreciseInteger(arguments[1]);
		AssertArgumentIsPreciseInteger(arguments[2]);
		AssertArgumentIsPreciseInteger(arguments[3]);
		AssertArgumentIsPreciseInteger(arguments[4]);
		
		this.milliseconds = ((24*60*60*1000*arguments[0]) + (60*60*1000*arguments[1]) + (60*1000*arguments[2]) + (1000*arguments[3]) + arguments[4]);
	}
	
	AssertArgumentIsPreciseInteger(this.milliseconds, 'milliseconds');
}

/*
 * Largest negative TimeSpan allowed
 * Ref: System.TimeSpan.MinValue
 */
CsoGateway.System.TimeSpan.MinValue = new CsoGateway.System.TimeSpan(-9007199254740992);

/*
 * Largest positive TimeSpan allowed
 * Ref: System.TimeSpan.MaxValue
 */
CsoGateway.System.TimeSpan.MaxValue	= new CsoGateway.System.TimeSpan(9007199254740992);

/*
 * Zero TimeSpan value.
 * Ref: System.TimeSpan.Zero
 */
CsoGateway.System.TimeSpan.Zero = new CsoGateway.System.TimeSpan(0);

/*
 * Gets the number of whole days represented by the current TimeSpan.
 * Ref: System.TimeSpan.Days
 */
CsoGateway.System.TimeSpan.prototype.Days = function()
{
	if(this.milliseconds >= 0)
		return Math.floor(this.milliseconds/(1000*60*60*24));
	else
		return Math.ceil(this.milliseconds/(1000*60*60*24));
}

/*
 * Gets the number of whole hours represented by the current TimeSpan. Returns integer between -23 and 23 incl.
 * Ref: System.TimeSpan.Hours
 */
CsoGateway.System.TimeSpan.prototype.Hours = function()
{
	if(this.milliseconds >= 0)
		return Math.floor((this.milliseconds%(1000*60*60*24))/(1000*60*60));
	else
		return Math.ceil((this.milliseconds%(1000*60*60*24))/(1000*60*60));
}

/*
 * Gets the number of milliseconds represented by the current TimeSpan. Returns integer between -999 and 999 incl.
 * Ref: System.TimeSpan.Milliseconds
 */
CsoGateway.System.TimeSpan.prototype.Milliseconds = function()
{
	return this.milliseconds%1000;
}

/*
 * Gets the number of whole minutes represented by the current TimeSpan. Returns integer between -59 and 59 incl.
 * Ref: System.TimeSpan.Minutes
 */
CsoGateway.System.TimeSpan.prototype.Minutes = function()
{
	if(this.milliseconds >= 0)
		return Math.floor((this.milliseconds%(1000*60*60))/(1000*60));
	else
		return Math.ceil((this.milliseconds%(1000*60*60))/(1000*60));
}

/*
 * Gets the number of whole seconds represented by the current TimeSpan. Returns integer between -59 and 59 incl.
 * Ref: System.TimeSpan.Seconds
 */
CsoGateway.System.TimeSpan.prototype.Seconds = function()
{
	if(this.milliseconds >= 0)
		return Math.floor((this.milliseconds%(1000*60))/(1000));
	else
		return Math.ceil((this.milliseconds%(1000*60))/(1000));
}

/*
 * Gets the value of the current TimeSpan expressed in whole and fractional days.
 * Ref: System.TimeSpan.TotalDays
 */
CsoGateway.System.TimeSpan.prototype.TotalDays = function()
{
	return this.milliseconds/(1000*60*60*24);
}

/*
 * Gets the value of the current TimeSpan expressed in whole and fractional hours.
 * Ref: System.TimeSpan.TotalHours
 */
CsoGateway.System.TimeSpan.prototype.TotalHours = function()
{
	return this.milliseconds/(1000*60*60);
}

/*
 * Gets the value of the current TimeSpan expressed in milliseconds.
 * Ref: System.TimeSpan.TotalMilliseconds
 */
CsoGateway.System.TimeSpan.prototype.TotalMilliseconds = function()
{
	return this.milliseconds;
}

/*
 * Gets the value of the current TimeSpan expressed in whole and fractional minutes.
 * Ref: System.TimeSpan.TotalMinutes
 */
CsoGateway.System.TimeSpan.prototype.TotalMinutes = function()
{
	return this.milliseconds/(1000*60);
}

/*
 * Gets the value of the current TimeSpan expressed in whole and fractional seconds.
 * Ref: System.TimeSpan.TotalSeconds
 */
CsoGateway.System.TimeSpan.prototype.TotalSeconds = function()
{
	return this.milliseconds/(1000);
}

/*
 * Adds the specified TimeSpan to this instance.
 * Ref: System.TimeSpan.Add(TimeSpan)
 */
CsoGateway.System.TimeSpan.prototype.Add = function(ts)
{
	AssertArgumentType(ts, TimeSpan, 'ts');

	return new TimeSpan(this.milliseconds + ts.milliseconds);
}

/*
 * Static method.
 * Compares two TimeSpan values and returns an integer that indicates their relationship. Returns -1
 * if ts1 is less than ts2, 0 if they are equal and +1 if ts1 is greater than ts2.
 * Ref: System.TimeSpan.Compare(TimeSpan, TimeSpan)
 */
CsoGateway.System.TimeSpan.Compare = function(ts1, ts2)
{
	AssertArgumentType(ts1, TimeSpan, 'ts1');
	AssertArgumentType(ts2, TimeSpan, 'ts2');

	if(ts1.milliseconds < ts2.milliseconds)
		return -1;
	else if(ts1.milliseconds == ts2.milliseconds)
		return 0;
	else if(ts1.milliseconds > ts2.milliseconds)
		return 1;
}

/*
 * Compares this instance to a specified object or TimeSpan and returns an indication of their relative values.
 * Returns -1 if ts1 is less than ts2, 0 if they are equal and +1 if ts1 is greater than ts2.
 * Ref: System.TimeSpan.CompareTo(TimeSpan)
 */
CsoGateway.System.TimeSpan.prototype.CompareTo = function(ts)
{
	return TimeSpan.Compare(this, ts);
}

/*
 * Returns a new TimeSpan object whose value is the absolute value of the current TimeSpan object. 
 * Ref: System.TimeSpan.Duration(TimeSpan)
 */
CsoGateway.System.TimeSpan.prototype.Duration = function()
{
	return new TimeSpan(Math.abs(this.milliseconds));
}

/*
 * Returns a value indicating whether this instance is equal to a specified TimeSpan object. 
 * Ref: System.TimeSpan.Equals(TimeSpan)
 */
CsoGateway.System.TimeSpan.prototype.Equals = function(ts)
{
	AssertArgumentType(ts, TimeSpan, 'ts');

	return (this.milliseconds === ts.milliseconds);
}

/*
 * Static method.
 * Returns a TimeSpan that represents a specified number of days, where the specification is accurate to the nearest millisecond. 
 * Ref: System.TimeSpan.FromDays(System.Double)
 */
CsoGateway.System.TimeSpan.FromDays = function(value)
{
	AssertArgumentType(value, Number, 'value');
	return new TimeSpan(Math.round(value*24*60*60*1000));
}

/*
 * Static method.
 * Returns a TimeSpan that represents a specified number of hours, where the specification is accurate to the nearest millisecond. 
 * Ref: System.TimeSpan.FromHours(System.Double)
 */
CsoGateway.System.TimeSpan.FromHours = function(value)
{
	AssertArgumentType(value, Number, 'value');
	return new TimeSpan(Math.round(value*60*60*1000));
}

/*
 * Static method.
 * Returns a TimeSpan that represents a specified number of milliseconds, where the specification is accurate to the nearest millisecond. 
 * Ref: System.TimeSpan.FromMilliseconds(System.Double)
 */
CsoGateway.System.TimeSpan.FromMilliseconds = function(value)
{
	AssertArgumentType(value, Number, 'value');
	return new TimeSpan(Math.round(value));
}

/*
 * Static method.
 * Returns a TimeSpan that represents a specified number of minutes, where the specification is accurate to the nearest millisecond. 
 * Ref: System.TimeSpan.FromMinutes(System.Double)
 */
CsoGateway.System.TimeSpan.FromMinutes = function(value)
{
	AssertArgumentType(value, Number, 'value');
	return new TimeSpan(Math.round(value*60*1000));
}

/*
 * Static method.
 * Returns a TimeSpan that represents a specified number of seconds, where the specification is accurate to the nearest millisecond. 
 * Ref: System.TimeSpan.FromSeconds(System.Double)
 */
CsoGateway.System.TimeSpan.FromSeconds = function(value)
{
	AssertArgumentType(value, Number, 'value');
	return new TimeSpan(Math.round(value*1000));
}

/*
 * Returns a TimeSpan whose value is the negated value of this instance. 
 * Ref: System.TimeSpan.Negate()
 */
CsoGateway.System.TimeSpan.prototype.Negate = function()
{
	return new TimeSpan(this.milliseconds * -1);
}

/*
 * Constructs a new TimeSpan object from a time interval specified in a string. 
 * Ref: System.TimeSpan.Parse(string)
 */
CsoGateway.System.TimeSpan.prototype.Parse = function(s)
{
	throw new Error.notImplemented()
}

/*
 * Subtracts the specified TimeSpan from this instance and returns the result as a new TimeSpan object.
 * Ref: System.TimeSpan.Substract(System.TimeSpan)
 */
CsoGateway.System.TimeSpan.prototype.Substract = function(ts)
{
	AssertArgumentType(ts, TimeSpan, 'ts');
	return new TimeSpan(this.milliseconds - ts.milliseconds);
}

/*
 * Returns the string representation of the value of this instance.
 * Ref: System.TimeSpan.ToString()
 */
CsoGateway.System.TimeSpan.prototype.ToString = function()
{
	abs = this.Duration();
	return ((this.milliseconds<0) ? '-' : '') + ((abs.Days()!=0) ? (abs.Days().toString()+'.') : '') + abs.Hours().toString() + ':' + abs.Minutes().toString() + ':' +
		abs.Seconds().toString() + (abs.Milliseconds()!=0 ? ('.' + (abs.Milliseconds()/1000).toFixed(3).substring(2)) : '')
}

/*
 * Returns the string representation of the value of this instance.
 * Ref: System.TimeSpan.ToString()
 */
CsoGateway.System.TimeSpan.prototype.toString = function()
{
	return this.ToString();
}

/*
 * Register the class CsoGateway.System.TimeSpan
 */
CsoGateway.System.TimeSpan.registerClass('CsoGateway.System.TimeSpan', CsoNative, Sys.IDisposable);

/*
 * End of CsoGateway.System.TimeSpan definition
 */